package com.qianfeng.smartplatform.service.impl;

//
//                            _ooOoo_  
//                           o8888888o  
//                           88" . "88  
//                           (| -_- |)  
//                            O\ = /O  
//                        ____/`---'\____  
//                      .   ' \\| |// `.  
//                       / \\||| : |||// \  
//                     / _||||| -:- |||||- \  
//                       | | \\\ - /// | |  
//                     | \_| ''\---/'' | |  
//                      \ .-\__ `-` ___/-. /  
//                   ___`. .' /--.--\ `. . __  
//                ."" '< `.___\_<|>_/___.' >'"".  
//               | | : `- \`.;`\ _ /`;.`/ - ` : | |  
//                 \ \ `-. \_ __\ /__ _/ .-` / /  
//         ======`-.____`-.___\_____/___.-`____.-'======  
//                            `=---='  
//  
//         .............................................  
//                  佛祖镇楼                  BUG辟易  
//          佛曰:  
//                  写字楼里写字间，写字间里程序员；  
//                  程序人员写程序，又拿程序换酒钱。  
//                  酒醒只在网上坐，酒醉还来网下眠；  
//                  酒醉酒醒日复日，网上网下年复年。  
//                  但愿老死电脑间，不愿鞠躬老板前；  
//                  奔驰宝马贵者趣，公交自行程序员。  
//                  别人笑我忒疯癫，我笑自己命太贱；  
//  


import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.qianfeng.smartplatform.cache.DefaultRoleCache;
import com.qianfeng.smartplatform.cache.RoleCache;
import com.qianfeng.smartplatform.constants.ResultEnum;
import com.qianfeng.smartplatform.constants.StatusConstants;
import com.qianfeng.smartplatform.dto.UserDto;
import com.qianfeng.smartplatform.exceptions.AddErrorException;
import com.qianfeng.smartplatform.exceptions.DeleteErrorException;
import com.qianfeng.smartplatform.exceptions.QueryDataException;
import com.qianfeng.smartplatform.exceptions.UpdateErrorException;
import com.qianfeng.smartplatform.mapper.UserMapper;
import com.qianfeng.smartplatform.pojo.*;
import com.qianfeng.smartplatform.security.BaseUser;
import com.qianfeng.smartplatform.service.UserRoleService;
import com.qianfeng.smartplatform.service.UserService;
import com.qianfeng.smartplatform.utils.SecurityUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * Created by Jackiechan on 2021/12/20/23:31
 *
 * @author Jackiechan
 * @version 1.0
 * @since 1.0
 */
@Service
@Transactional
public class UserServiceImpl implements UserService {

    private UserMapper userMapper;

    private DefaultRoleCache defaultRoleCache;

    private RoleCache roleCache;

    private UserRoleService userRoleService;

    private ThreadPoolExecutor complateFutureExecutor;

    @Autowired
    public void setComplateFutureExecutor(ThreadPoolExecutor complateFutureExecutor) {
        this.complateFutureExecutor = complateFutureExecutor;
    }
    @Autowired
    public void setUserRoleService(UserRoleService userRoleService) {
        this.userRoleService = userRoleService;
    }

    @Autowired
    public void setUserMapper(UserMapper userMapper) {
        this.userMapper = userMapper;
    }

    @Autowired
    public void setRoleCache(RoleCache roleCache) {
        this.roleCache = roleCache;
    }

    @Autowired
    public void setDefaultRoleCache(DefaultRoleCache defaultRoleCache) {
        this.defaultRoleCache = defaultRoleCache;
    }

    private BCryptPasswordEncoder bCryptPasswordEncoder;

    @Autowired
    public void setbCryptPasswordEncoder(BCryptPasswordEncoder bCryptPasswordEncoder) {
        this.bCryptPasswordEncoder = bCryptPasswordEncoder;
    }

    @Override
    public int addUser(UserDto userDto) {
        return 0;
    }

    @Override
    public int registry(UserDto userDto) {
        User user = new User();
        BeanUtils.copyProperties(userDto, user);
        Assert.isTrue(userDto!=null&&!user.isEmpty(CheckType.ADD),  () -> {
            throw new AddErrorException(ResultEnum.NULL_DATA);
        });
        //判断手机号是否符合规则

        //数据已经存在
        Assert.isNull(getUserByPhone(user.getPhone()),()->{
            throw new AddErrorException(ResultEnum.DATA_ALLREADY_EXIST);
        });
        //按照用户名查询下判断是否存在
        Assert.isNull(getUserByUsername(user.getUsername()),()->{
            throw new AddErrorException(ResultEnum.DATA_ALLREADY_EXIST);
        });
        //如果传递了邮箱,则按照邮箱查询一次
        if (StringUtils.hasText(user.getEmail())) {
            //应该要先判断邮箱的格式是否符合要求
            Assert.isNull(getUserByMail(user.getEmail()),()->{
                throw new AddErrorException(ResultEnum.DATA_ALLREADY_EXIST);
            });
        }

        //设置密码
        //1 生成随机的盐,盐在使用bCryptPasswordEncoder后不再启用

        //2 将密码设置为转换后的内容
        String passworsEncode = bCryptPasswordEncoder.encode(user.getPassword());
        user.setPassword(passworsEncode);
        //设置创建时间
        user.setCreateTime(new Date());
        //注册的用户创建者就是自己
        user.setCreateBy(user.getUsername());
        //查找默认的用户类型, 注册用户的普通类型和后台管理员添加的用户的默认类型不一致,普通用户只能注册
        DefaultRole defaultRole = defaultRoleCache.get("user");
        //设置类型
        user.setRemark(roleCache.get(defaultRole.getRoleId()).getRemark());
        int result = userMapper.insertSelective(user);
       // System.err.println(user);
        //顺便给用户分配角色
        CompletableFuture.runAsync(()->{
            UserRoleKey userRoleKey = new UserRoleKey();
            userRoleKey.setUserId(user.getuId());
            userRoleKey.setRoleId(defaultRole.getRoleId());
            userRoleService.addRole2User(userRoleKey);
        },complateFutureExecutor);
        return result;
    }

    @Override
    public Integer getUserIdByUserName(String username) {
        //必须传递用户名才可以查询数据
        Assert.hasText(username,()->{
            throw new QueryDataException(ResultEnum.NULL_DATA);
        });
        return userMapper.selectIdByUserName(username);
    }

    @Override
    public User getUserByUsername(String username) {
        Assert.hasText(username,()->{
            throw new QueryDataException(ResultEnum.NULL_DATA);
        });
        return userMapper.selectByUserName(username);
    }

    @Override
    public User getUserByPhone(String phone) {
        Assert.hasText(phone,()->{
            throw new QueryDataException(ResultEnum.NULL_DATA);
        });
        return userMapper.selectByPhone(phone);
    }

    @Override
    public User getUserByMail(String email) {
        Assert.hasText(email,()->{
            throw new QueryDataException(ResultEnum.NULL_DATA);
        });
        return userMapper.selectByEmail(email);
    }

    @Override
    public User getUserByUId(Integer id) {
        Assert.isTrue(!ObjectUtils.isEmpty(id)&&id>0,()->{
            throw new QueryDataException(ResultEnum.ID_NULL);
        });
        return userMapper.selectByPrimaryKey(id);
    }

    @Override
    public PageInfo<User> findAllUsers(int pageNum, int pageSize, Short status, String username) {
        PageHelper.startPage(pageNum, pageSize);
        UserExample userExample = new UserExample();
        UserExample.Criteria criteria = userExample.createCriteria();
        //设置条件
        if (StringUtils.hasText(username)) {
            criteria.andUsernameLike(username);
        }
        if (!ObjectUtils.isEmpty(status) && status >= 0) {
            criteria.andStatusEqualTo(status);
        }
        List<User> userList = userMapper.selectByExampleWithBLOBs(userExample);
        return new PageInfo<>(userList);
    }

    @Override
    public int updateUserLoginInfoById(String username, Date loginDate,String ip){
        return 0;
    }

    @Override
    public int updateUserLoginInfoByUserName(String username, Date loginDate,String ip) {
        userMapper.updateUserLoginInfoByUserName(username,loginDate,ip);
        return 0;
    }

    @Override
    public int updateUser(UserDto userDto) {
        //普通用户不能更新用户名,如果业务需求决定管理员可以修改用户名, 则此处需要对正在进行操作的用户进行判断
        User user = new User();
        BeanUtils.copyProperties(userDto,user);//拷贝数据到pojo对象上
        Assert.isTrue(!user.isEmpty(CheckType.UPDATE),()->{
            throw new UpdateErrorException(ResultEnum.NULL_DATA);
        });
        //如果是更新自己的数据,则不可以更新用户名
        BaseUser currentLogin = SecurityUtils.getUser();//获取当前登陆的用户
        Integer id = currentLogin.getId();//获取到当前用户的id
//        if (id == user.getuId()&&StringUtils.hasText(user.getUsername())) {
//            //用户期望更新用户名
//        }
        Assert.isTrue(id !=user.getuId()||!StringUtils.hasText(user.getUsername()),()->{
            //期望不是用户要更改自己的用户名
            throw new UpdateErrorException(ResultEnum.CAN_NOT_UPDATE_USERNAME);
        });
        //设置更新者和更新时间
        user.setUpdateBy(currentLogin.getUsername());
        user.setUpdateTime(new Date());
        int result = userMapper.updateByPrimaryKeyWithBLOBs(user);//更新用户

        return result;
    }

    @Override
    public void deleteUsers(List<Integer> ids) {
        //普通用户不能进行删除操作,只能是具有管理员权限的人才可以删除, 可以通过禁止普通用户访问delelte接口来实现
        BaseUser currentLogin = SecurityUtils.getUser();//获取当前登陆的用户
        String username = currentLogin.getUsername();//
        Integer id = currentLogin.getId();
        //根据业务需要觉得是否可以自己删除自己,如果不能,则需要判断id中是否包含自己,包含的话需要删除
        ids.remove(id);
        Assert.notEmpty(ids,()->{
            throw new DeleteErrorException(ResultEnum.ID_NULL);//更新需要传递id
        });

        UserExample userExample = new UserExample();
        userExample.createCriteria().andUIdIn(ids);
        User user = new User();
        user.setStatus(StatusConstants.DISABLE);
        user.setUpdateTime(new Date());
        user.setUpdateBy(username);
        int result = userMapper.updateByExampleWithBLOBs(user, userExample);//更新数据
        Assert.isTrue(result>0,()->{
            throw new DeleteErrorException(ResultEnum.DATA_NOT_EXIST);//数据不存在
        });
    }

    @Override
    public User getUserWithPermisByUserName(String username) {
        return null;
    }



}
